<?php

namespace App\Models;

use App\Enums\DomainSource;
use App\Enums\DomainType;
use App\Models\Traits\BelongsToApplication;
use App\Models\Traits\HasEasyStatus;
use Exception;
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;

class DomainPool extends Model
{
    use BelongsToApplication,
        Cachable,
        HasEasyStatus,
        SoftDeletes;

    protected $casts = [
        'source' => DomainSource::class,
        'type' => DomainType::class,
        'ssl' => 'bool',
        'verify' => 'bool',
    ];

    protected static function boot(): void
    {
        parent::boot();

        self::deleting(function (DomainPool $pool) {
            if ($pool->spiders()->count()) {
                throw new Exception('域名正在使用中，请解除关联后再删除！');
            }
        });
    }

    public function spiders(): HasMany
    {
        return $this->hasMany(Spider::class);
    }

    public function aliyun(): BelongsTo
    {
        return $this->belongsTo(Aliyun::class);
    }

    public function objectStorageService(): BelongsTo
    {
        return $this->belongsTo(ObjectStorageService::class, 'oss_id');
    }

    public function storage(bool $cdn = false): Filesystem
    {
        return $this->objectStorageService->storage(($cdn && $this->ssl) ? $this->domain : null, $this->ssl);
    }

    /**
     * Notes   : 生成对应的二级域名
     *
     * @Date   : 2024/8/5 下午4:36
     * @Author : <Jason.C>
     * @param  string  $prefix
     * @return string
     */
    public function makeSubDomain(string $prefix): string
    {
        $domain = $this->domain;

        if ($this->ssl) {
            $scheme = 'https://';
        } else {
            $scheme = 'http://';
        }
        if (Str::startsWith($domain, '*.')) {
            return $scheme.$prefix.str_replace('*', '', $domain);
        } else {
            return $scheme.$domain.'/'.$this->type->value.'/'.$prefix;
        }
    }

    public function certificates(): HasMany
    {
        return $this->hasMany(Certificate::class);
    }
}
